#include <cstdlib>
#include <cstring>

#include "libnet_error.h"
#include "net_buffer.h"


int32_t CNetBuffer::Init(size_t ulBufLen)
{
    // 初始化一定数量的空闲Item

    for (int i = 0; i < 1024; i++)
    {
        char* pcBuf = (char*)malloc(ulBufLen);
        if (pcBuf == nullptr)
        {
            return ERROR_NO_MEMORY;
        }

        m_objFreeList.push_front({pcBuf, nullptr, ulBufLen, 0});
    }

    return ERROR_SUCCESS;
}

int32_t CNetBuffer::AddData(const void* pData, size_t ulDataLen)
{
    // 先判断Used尾结点空间是否足够，如果不够则从FreeList中获取一个空闲的Item

    if (!m_objUsedList.empty())
    {
        BUFFER_ITEM_S& refBackItem = m_objUsedList.back();

        size_t ulLeftLen = refBackItem.ulSize - refBackItem.ulDataLen;

        if (ulLeftLen >= ulDataLen)
        {
            memcpy(refBackItem.pcStart + refBackItem.ulDataLen, pData, ulDataLen);

            return 0;
        }
    }

    if (m_objFreeList.empty())
    {
        return -1;
    }

    BUFFER_ITEM_S& refFreeItem = m_objFreeList.front();
    m_objFreeList.pop_front();

    if (refFreeItem.ulSize >= ulDataLen)
    {
        memcpy(refFreeItem.pcStart, pData, ulDataLen);
        m_objUsedList.emplace_back(refFreeItem);

        return 0;
    }

    m_objFreeList.emplace_front(refFreeItem);

    return -1;
}

bool CNetBuffer::GetItem(BUFFER_ITEM_S& refItem)
{
    if (!m_objUsedList.empty())
    {
        refItem = m_objUsedList.front();
        m_objUsedList.pop_front();
        return true;
    }

    return false;
}

void CNetBuffer::PushBack(BUFFER_ITEM_S& refItem)
{
    m_objUsedList.emplace_front(refItem);
}

void CNetBuffer::Free(BUFFER_ITEM_S& refItem)
{
    refItem.pcData = nullptr;
    refItem.ulDataLen = 0;
    m_objFreeList.emplace_front(refItem);
}

bool CNetBuffer::Empty()
{
    return m_objUsedList.empty();
}